
//contiene un listado de funciones para construir meshes
var mapA = THREE.ImageUtils.loadTexture( "imagenes/landmarks/sprite1.png" );
MESH_LIBRARY_FUNCTIONS = {
	
		getFaceMaterialMesh : function(geometry){
			//return new THREE.Mesh(geometry, new THREE.MeshFaceMaterial());
			return new THREE.Mesh(geometry, MaterialBuilder.MeshFaceMaterial);
		},
		
		getWallMesh : function(params){
			
			if (!params.material) {alert('falta el material!')}
			
			var geo = new ParedGeometry(params.puntos, params.altura); 
			
			geo.materials.push(params.material);
			for ( var face in geo.faces ) {
				geo.faces[ face ].materialIndex = 0; //el material lo asigno a la geometria y no a la malla (faceMaterial)
			}
			
			var mesh = new THREE.Mesh(geo, MaterialBuilder.MeshFaceMaterial);
			return mesh;
		},
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//--------------------------------------------- GET CENTERED SPRITE ------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//params.posicion = posicion donde se dibujara el sprite
	//params.texto = texto que se posiciona sobre el sprite al ser seleccionado (ej: nombre del aula)
	
	getCenteredSprite : function(params){
		
		var posicion = params.posicion || {x:0, y:0, z:0};
		posicion.y += 16;//TODO

		var map = params.map != undefined ? params.map : mapA;
		
		var sprite = new THREE.Sprite( { map: map, useScreenCoordinates: false, color: 0xffffff } );

		var initialScale = params.initialScale || 1;
		sprite.scale.set(initialScale, initialScale );
		
		sprite.position.set( posicion.x, posicion.y,	posicion.z);//+16: la altura del sprite es 32
		
		sprite.textTFC = params.texto; //Variable agregada
	
		sprite.select = function(x, y){
			//this.map =  sprite.map = THREE.ImageUtils.loadTexture( "imagenes/landmarks/sprite0.png" );
			//prite.opacity = 1;
			this.scale.set(1.3, 1.3 );
			this.position.y = posicion.y + 5;
		};
		
		sprite.unselect = function(){
			this.scale.set( initialScale, initialScale );
			this.position.y = posicion.y;
			// this.map =  sprite.map = THREE.ImageUtils.loadTexture( "imagenes/landmarks/sprite1.png" );
			//sprite.opacity = 0.25;
		};

		// add 2d-sprites

		//sprite = new THREE.Sprite( { map: mapA, alignment: THREE.SpriteAlignment.topLeft } );
		//sprite.position.set( 100, 100, 0 );
		//sprite.opacity = 0.25;
		//scene.add( sprite );
		return sprite;
	},
	
	
	
	
	
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//------------------------------------------------ GET SHAPE MESH -----------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//params.puntos = puntos que representan al shape
	//params.color = color del shape ////deprecated (esta defido en el MaterialBuilder)
	
	//params.tipo = determina elt tipo del space (office, classroom, corridor, etc) de esto dependera el material que se utilizara
	
	//params.nivel
	
	//params.extrudeCorridor
	//params.extrudeOthers
	//retorna el mesh
	getShapeMesh : function(params){
		
		if (!params.material) {alert('falta el material!')}
		//inicializacion variables	
		var puntos = params.puntos || [];
		var extrudeValue = params.extrudeValue || 0;
		var bevelEnabled = params.bevelEnabled !== undefined ? params.bevelEnabled : false;
		
		if (puntos.length < 3) return;	
		
		//armamos el shape
		var shape = new THREE.Shape();
		shape.moveTo(puntos[0].x, puntos[0].z);
		
		for (var i = 1; i<puntos.length; i++){
			shape.lineTo( puntos[i].x, puntos[i].z);
		}
		
		shape.lineTo(puntos[0].x, puntos[0].z);//cierro el shape (uno el ultimo punto con el primero)
		
		var shapeGeo = shape.extrude({	amount:extrudeValue,  bevelEnabled: bevelEnabled} );
		shapeGeo.materials.push(params.material);
		for ( var face in shapeGeo.faces ) {
			shapeGeo.faces[ face ].materialIndex = 0; //el material lo asigno a la geometria y no a la malla (faceMaterial)
		}
		
		// 3d shape
		var mesh = new THREE.Mesh( shapeGeo, MaterialBuilder.MeshFaceMaterial);
		if (puntos[0].y != undefined && puntos[0].y != null) mesh.position.y = puntos[0].y + extrudeValue;
		mesh.rotation.x = Math.PI/2;

		return mesh;
	},
	
	
	
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//-------------------------------------------- GET STAIR MESH ---------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//params.target = escena/objeto en la que se agregara el mesh generado
	//params.tipo = tipo de escalera a dibujar
	//params.puntos = puntos que forman el contorno de la escalera (bounding rectangle)
	//params.sourcePointIndex = indice del punto que marca el inicio para la escalera
	//params.color = color del shape
	//retorna el mesh
	getStairMesh : function(params, materialBuilder){
	if ( !params.puntos || !params.material) {alert('falto el material en getstairmesh'); return;}

		var puntos = params.puntos ;
		var tipo = params.tipo || 'ustair';
		var paredesBool = params.paredesEscalera !== undefined? params.paredesEscalera : false;
		
		
		var p1 = puntos[0],
			p2 = puntos[1],
			p3 = puntos[2],
			p4 = puntos[3];
		
		var mult = (tipo == 'ustair')? 1 : -1;
		
		var ancho = Math.sqrt(Math.pow(p1.x - p2.x,2)+Math.pow(p1.z - p2.z,2));
		var largo = Math.sqrt(Math.pow(p1.x - p4.x,2)+Math.pow(p1.z - p4.z,2));
		var alto = params.alto || 50; //TODO no tengo los valores todavia
		
		var bevelOn = (params.bevel != undefined)? params.bevel : true;
	//	cantEscalones = 10;
	//	altoEscalon = alto/cantEscalones;
	//	largoEscalon = largo/cantEscalones;
		
		var largoEscalon = 6;
		var cantEscalones = truncate(largo/largoEscalon);//truncamos el numero
		largoEscalon += (largo - (cantEscalones*largoEscalon))/cantEscalones;
		altoEscalon = (alto/cantEscalones);
		
		function truncate(n) { return Math[n > 0 ? "floor" : "ceil"](n);}
		
		
		var geometryEscalera = new THREE.Geometry();
		
		
		
		/*ARMAMOS LA GEOMETRIA*/		
		if (false && bevelOn){ //var global
			
			var shape = new THREE.Shape();
			var puntos = [
			              {x: -largoEscalon/2, z: altoEscalon/2  },
			              {x: largoEscalon/2, z: altoEscalon/2  },
			              {x: largoEscalon/2, z: -altoEscalon/2  },
			              {x: -largoEscalon/2, z: -altoEscalon/2  },
			              ];
			
			shape.moveTo(puntos[0].x, puntos[0].z);
			
			for (var i = 1; i<puntos.length; i++){
				shape.lineTo( puntos[i].x, puntos[i].z);
			}
			
			shape.lineTo(puntos[0].x, puntos[0].z);//cierro el shape (uno el ultimo punto con el primero)
			
			var shapeGeo = shape.extrude({	amount:ancho,  bevelEnabled: true} );
			cubeGeo = shapeGeo;
			
			for (var i = 0; i < cantEscalones; i++){
				var mesh = new THREE.Mesh(cubeGeo);
				mesh.position.x = i*largoEscalon + largoEscalon/2; //mueve el escalon para arriba o para abajo
				mesh.position.z = -ancho/2; //mueve el escalon para arriba o para abajo
				mesh.position.y = i*altoEscalon*mult; + altoEscalon/2*mult;//mueve el escalon para adelante o para atras
				
				THREE.GeometryUtils.merge(geometryEscalera, mesh);
			}
			
		}else{
			
			var cubeGeo = new THREE.CubeGeometry( largoEscalon, altoEscalon, ancho, 1, 1, 1 );
			for (var i = 0; i < cantEscalones; i++){
				var mesh = new THREE.Mesh(cubeGeo);
				mesh.position.x = i*largoEscalon + largoEscalon/2;
				mesh.position.y = i*altoEscalon*mult + altoEscalon/2*mult +altoEscalon; //este altoEscalon*2 es por el bevel de los spaces 
				
				THREE.GeometryUtils.merge(geometryEscalera, mesh);
			}
			
			//paredes laterales de la escalera
			if (paredesBool){
				var paredLateral = []; //si funciona, meter en el for anterior
				
				if (tipo == 'ustair'){
					paredLateral.push({x: 0, z: 0 });
				}else{
					paredLateral.push({x: 0, z: -alto });
				}
				
				var aux = tipo == 'ustair' ? 1 : 0
				for (var i = 0; i < cantEscalones; i++){
					paredLateral.push({x: (i*largoEscalon), z: ((i+ aux)*altoEscalon*mult )});
					paredLateral.push({x: ((i+1)*largoEscalon), z: ((i + aux)*altoEscalon*mult)});
				}
				
				if (tipo == 'ustair'){
					paredLateral.push({x:  cantEscalones*largoEscalon, z: 0 });	
				}else{
					paredLateral.push({x: cantEscalones*largoEscalon, z: -alto });
				}
				
				
				var paramsMesh = {};
				paramsMesh.puntos = paredLateral;
				paramsMesh.bevelEnabled = false;
				paramsMesh.material =  params.material;

				var m1 = MESH_LIBRARY_FUNCTIONS.getShapeMesh(paramsMesh);
				m1.rotation.x = 0;
				m1.position.z = ancho/2;
//				
				var m2 = MESH_LIBRARY_FUNCTIONS.getShapeMesh(paramsMesh);
				m2.rotation.x = 0;
				m2.position.z = -ancho/2;
				
				THREE.GeometryUtils.merge(geometryEscalera, m1);
				THREE.GeometryUtils.merge(geometryEscalera, m2);
			}
			
		}
		/*fin ARMAMOS LA GEOMETRIA*/
		
		/*ESTRUCTURA MERGEADA. SETEAMOS LOS MATERIALES POR CARA*/
		geometryEscalera.dynamic = true;//era para animar el color de la escalera
		geometryEscalera.materials.push( params.material);
		for ( var face in geometryEscalera.faces ) {
			geometryEscalera.faces[ face ].materialIndex = 0; //el material lo asigno a la geometria y no a la malla (faceMaterial)
		}
			
		/*CREACION DE LA MALLA*/
		var mesh = new THREE.Mesh(geometryEscalera, MaterialBuilder.MeshFaceMaterial );//new THREE.Object3D();
			
		/*ALINEACION DE LA MALLA*/
		var dir;
		if (params.intra_floor){
			dir = new THREE.Vector3(p4.x-p1.x,
					0,//p3.y-p1.y,
					p4.z-p1.z).normalize();
		}else{
			alert("no deberia haber entrado aca");
			dir = (new THREE.Vector3(p4.x-p1.x,p4.y-p1.y,p4.z-p1.z)).normalize();
		}
		
		var puntoMedioInicio = new THREE.Vector3(p2.x - (p2.x-p1.x)/2,
				p2.y-(p2.y-p1.y)/2,
				p2.z-(p2.z-p1.z)/2); 
		var ejeX = new THREE.Vector3(1,0,0);
		
		var dot = Math.acos(dir.dot(ejeX));
		if (Math.abs(dir.x) <  0.05 && Math.abs(dir.z -1) <0.05)dot = -dot;
	
		mesh.rotation.y = dot;
		mesh.translateX( puntoMedioInicio.x);
		mesh.translateZ( puntoMedioInicio.z); 
		mesh.cantEscalones = cantEscalones;
		
		mesh.doubleSided = true;
		return mesh;
	},
	
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//--------------------------------------------- GET CENTERED TEXT MESH ------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//params.targetObject = escena/objeto_3D al que se agregara la malla creada
	//params.posicion = posicion donde se dibujara el texto
	//params.texto = texto que se posiciona sobre el centroide (ej: nombre del aula)
	//params.punteroATexto = si esto esta en true, se retorna un objeto de la forma {sphere : sphere, texto : texto} (con las mallas)
	//params.nivel
	//params.paramsTexto
	getCenteredTextMesh : function(params){
		
	
		//representaci�n 3D del centroide del piso
	//	if (!params.targetObject) return;
	
		var targetObject = (params.targetObject)? params.targetObject : null;
		var posicion = params.posicion || {x:0, y:0, z:0};
		var texto = (params.texto == undefined || params.texto == null)? null : params.texto;
		var nivel = params.nivel;	
	//	var nivel = (params.nivel == undefined)? 0 : params.nivel;	
		padre = new THREE.Object3D();
		
		padre.translateX(posicion.x);
		padre.translateY(posicion.y);
		padre.translateZ(posicion.z);
		
		//if (texto)
		{
			var parametros = {"texto": texto, nivel: nivel};
			if (params.paramsTexto){
				for (var i in params.paramsTexto){
					parametros[i] = params.paramsTexto[i];
				}
			}
			texto3D = this.getTexto3D(parametros);
	//		texto3D.rotation(-Math.PI,0,0);
			texto3D.translateX(-texto3D.geometry.ancho()/2);
			texto3D.translateZ(-texto3D.geometry.profundidad/2);
			
			padre.add(texto3D);
		}
		
		if (targetObject){targetObject.add(padre);}///////////////////////////////////////-----////
		
		return padre;	
	
	},
	
	
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------- GET LANDMARK MESH ----------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//TODO por ahora .jpg
	//params.landmark : landmark a mostrar
	//params.parentObject : objeto padre al que se a�adira la malla creada
	//params.material
	getLandmarkMesh : function(params, materialBuilder){
		if (!params.landmark) return;
		
			
		var generarObjeto = function(mat){
			var width = mat.map.image.width;
			var height = mat.map.image.height;
			var escala = (width > height)? (CONSTANTS.LANDMARK_SIZE/width) : (CONSTANTS.LANDMARK_SIZE/height);//CONSTANTS.LANDMARK_SIZE = var global
			
			var geo = new THREE.PlaneGeometry(width, height, 1, 1);
			mesh = new THREE.Mesh( geo, mat);
			
			mesh.translateY(5);
			mesh.position.x = (params.landmark.centroid.x);// +(CONSTANTS.LANDMARK_SIZE - width*escala)/2 );
			mesh.position.z = (params.landmark.centroid.z);// +CONSTANTS.LANDMARK_SIZE/2);
		
			mesh.position.y = (params.landmark.parentSpace.height+5);// +CONSTANTS.LANDMARK_SIZE/2);
				
			mesh.rotation.x = -Math.PI/2;
			mesh.scale.multiplyScalar(escala);
			params.parentObject.add(mesh);
			 			
			
			params.landmark.setObjeto3D(mesh);
		}; 
			
				//TODO falta comprobar landmarks genericos
		
			//primero evaluo si existe un material ya creado para este tipo de landmark
			if (!materialBuilder.alreadyGenerated("landmark"+params.landmark.type, params.nivel)){			
			
							
				var callbackFunction = function(){
					map.needsUpdate = true;
					var mat = new THREE.MeshBasicMaterial( { map : map, transparent: true, alphaTest : 0.1,} );
									
					materialBuilder.setMaterial("landmark"+params.landmark.type, params.nivel, mat);
					generarObjeto(mat);
				} ;
				
				var map = THREE.ImageUtils.loadTexture(CONSTANTS.LANDMARKS_PATH+params.landmark.name+".png", null, callbackFunction );
				
			}else{
				var mat = materialBuilder.getMaterial("landmark"+params.landmark.type,params.nivel);
				generarObjeto(mat);
			}
	},
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//--------------------------------------------- GET TEXTO 3D ----------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//PARAMS
	//<texto> : texto que se quiere representar mediante una malla 3D
	//
	//<size> : tama�o del texto
	//<height> : profundidad
	//<hover> :
	//
	//<curveSegments> : segmentos de curva
	//
	//<bezelThickness> :
	//<bezelSize> :
	//<bezelEnabled> :
	//
	//<font> : tipo de letra [helvetiker, optimer, gentilis, droid sans, droid serif]
	//<weight> : peso [normal, bold]
	//<style> : estilo [normal];		
	getTexto3D : function(params, materialBuilder){
		
		text = (params.texto == undefined || params.texto == null || params.texto == "")? "." : params.texto;
		
		size = params.size || 10, //tamañoo del texto
		height = params.height || 4, //profundidad
		hover = params.hover || 30,
	
		curveSegments = params.curveSegments || 6,
	
		bezelThickness = params.bezelThickness || 2,
		bezelSize = params.bezelSize || 1.5,
		bezelEnabled = (params.bezelEnabled != undefined)? params.bezelEnabled : true,
	
		//font = params.font || "times_new_roman", 		// helvetiker, optimer, gentilis, droid sans, droid serif
		font = params.font || "gentilis", 		// helvetiker, optimer, gentilis, droid sans, droid serif
		weight = params.weight || "bold",		// normal bold
		style = params.style || "normal";		// normal italic
//		font = params.font || "optimer", 		// helvetiker, optimer, gentilis, droid sans, droid serif
//		weight = params.weight || "bold",		// normal bold
//		style = params.style || "normal";		// normal italic
	
		textGeo = new THREE.TextGeometry( text, {
	
			size: size, 
			height: height,
			curveSegments: curveSegments,
	
			font: font,
			weight: weight,
			style: style,
	
			bezelThickness: bezelThickness,
			bezelSize: bezelSize,
			bezelEnabled: bezelEnabled
	
		});
		textMaterial =  materialBuilder.getMaterial("texto",params.nivel);
	
		//parent = new THREE.Object3D();
		textGeo.computeBoundingBox();
		textGeo.ancho = UTILS.calcularAncho;
		textGeo.alto = UTILS.calcularAlto;
		textGeo.profundidad = height; //cuanto tiene de fondo
		
		textMesh1 = new THREE.Mesh( textGeo, textMaterial );
	//	textMesh1.ancho = calcularAnchoEscalado;
	//	textMesh1.alto = calcularAltoEscalado;
	//	textMesh1.rotation.x = -Math.PI/2;
	//	textMesh1.rotation.y = Math.PI * 2;	
		
		return textMesh1;
		
	}
};/*fin mesh library*/
